From WikiChip
Difference between revisions of "Module:core"

(Add space between package infos.)
(Handle partial pdata lookup failure.)
 
Line 86: Line 86:
 
     if #package_location > 1 then
 
     if #package_location > 1 then
 
         page_name = package_location[1] .. '/packages/' .. package_location[2]
 
         page_name = package_location[1] .. '/packages/' .. package_location[2]
         info = pdata['packages'][package_location[1]][package_location[2]]
+
         if pdata['packages'][package_location[1]] then
 +
            info = pdata['packages'][package_location[1]][package_location[2]]
 +
        end
 
     end
 
     end
 
     if mw.smw then
 
     if mw.smw then

Latest revision as of 23:45, 1 April 2023

To add this template, simple add
{{core}}
to the page and save. The chip infobox will have a small [Edit Values] button at the top-right corner which can be used to add values using a form.
local p = {}
local origArgs

function p.add_file_prefix(str)
  if string.match(string.lower(str), '^file:') then
    return str
  else
    return 'File:' .. str
  end
end

function p.add_separator(box, title)
  box:tag('tr')
           :tag('td')
           :attr('class', 'header')
           :attr('colspan', '2')
           :wikitext(title)
end

function add_header(box, str)
      box
        :tag('tr')
          :tag('td')
            :attr('class', 'header')
            :attr('colspan', '2')
            :wikitext(str)
end

function p.add_entry(value, right)
  local e = mw.html.create('tr')
  e:tag('td')
    :attr('class', 'label')
    :wikitext(value)
  e:node(right)
  return e   
end

function has_arg(name)
	-- The argument can exist and be empty or not exist at all
	return string.len(origArgs[name] or '') > 0
end

function arg(name)
	return origArgs[name]
end

function p.set_val(prop, val)
	p.frame:preprocess('{{#set: ' .. prop .. '=' .. val .. '}}')	
end

local function append_packaging_data(infobox, arg_name, pdata, add_space)
    local package_name = origArgs[arg_name]
    if not package_name or package_name == '' then return add_space end

    local need_space = add_space
    local function may_add_space()
        need_space = true
        if add_space then
            infobox:tag('tr'):tag('td'):attr('colspan', '2'):tag('hr')
            add_space = false
        end
    end

    local function show_error(text)
        infobox:wikitext('[[Category:Articles with invalid parameter in template]]')
        may_add_space()
        local e = mw.html.create('tr')
        e:tag('td')
            :attr('colspan', '2')
            :attr('style', 'color: #c00;')
            :wikitext(text)
        infobox:node(e)
    end

    -- Reject unexpected input, esp. smw.ask operators []:|?*~
    if mw.ustring.find(package_name, '[^%w %-+._,/]') then
        show_error('Invalid package name')
        return need_space
    end

    local package_location, info, result = {}
    local page_name = package_name
    for field in string.gmatch(package_name, "([^,]+),?") do
        table.insert(package_location, field)
    end
    if #package_location > 1 then
        page_name = package_location[1] .. '/packages/' .. package_location[2]
        if pdata['packages'][package_location[1]] then
            info = pdata['packages'][package_location[1]][package_location[2]]
        end
    end
    if mw.smw then
        result = mw.smw.ask('[[Category:all ic packages]][[' .. page_name .. ']]' ..
            '|?package|?package type|?package contacts|?package pitch' ..
            '|?package length|?package width|?package height|?socket')
    end
    local dim_props = {'package length', 'package width', 'package height'}
    if type(result) == 'table' and #result >= 1 and result[1]['package'] then
        info = result[1]
    else
        if not info then
            show_error('Unknown package "' .. package_name .. '"')
            return need_space
        end
        page_name = nil
        for i, name in ipairs(dim_props)
            do info[name] = info.p_size and info.p_size[i] or nil end
    end

    local function tabled(x) return type(x) == 'table' and x or { x } end
    local function show(label, text)
        if not text or text == '' then return end
        may_add_space()
        infobox:node(p.add_entry(label, mw.html.create('td'):wikitext(text)))
    end
    local function param(a)
        local prop_names = unpack(a)
        local text, sep = '', ''
        for i, prop_name in ipairs(tabled(prop_names)) do
            local values = info[prop_name] -- single value or table
            if values then
                local n_values = 0
                for j, value in ipairs(tabled(values)) do
                    if value and value ~= '' then
                        if a.set_prop then p.set_val(a.set_prop, value) end
                        text = text .. sep .. value
                        sep = a.sep or ', '
                        n_values = n_values + 1
                        if n_values >= (a.max_values or 1) then break end
                    end
                end
            end
        end
        return text
    end
    local p_type_text, p_type_abbr = param{{'package type', 'p_type'}}, ''
    if p_type_text ~= '' and mw.ustring.len(p_type_text) <= 10 then
        p_type_abbr = ' (' .. p_type_text .. ')'
        p_type_text = ''
    end
    local p_name = param{{'package', 'p_name'}, set_prop='package', max_values=10}
    if p_name ~= '' then
        if page_name then p_name = '[[' .. page_name .. '|' .. p_name .. ']]' end
        show('Package', p_name .. p_type_abbr)
    end
    show('Package Type', p_type_text)
    show('Dimension', param{dim_props, sep=' × '})
    show('Pitch', param{{'package pitch', 'p_pitch'}, max_values=2, sep=' × '})
    show('Contacts', param{{'package contacts', 'p_contacts'}})
    show('Socket', param{{'socket', 'p_socket'}, set_prop='socket', max_values=10})
    return need_space
end

function p.core(frame)
	
	p.frame = frame
    if frame == mw.getCurrentFrame() then
        origArgs = frame:getParent().args
    else
        origArgs = frame.args
    end
	
	
    local infobox = mw.html.create('table')

    infobox
        :attr('class', 'infobox')
        
    infobox
    	:tag('tr')
			:tag('td'):attr('colspan', '2')
			:tag('small'):attr('style', 'float: left; font-weight: bold;')
            :wikitext('[[Special:FormEdit/core/' .. frame:preprocess('{{FULLPAGENAME}}') .. '|<i class="fa fa-edit"></i>Edit Values]]')

    -- header
    if has_arg('name') then
      infobox
        :tag('tr')
          :tag('td')
            :attr('class', 'header-main')
            :attr('colspan', '2')
            :wikitext('[[name::' .. arg('name') .. ']]')
    end
    
    -- image
    for i = 1, 10 do
    	local name = (i == 1) and "" or " " .. i
		if has_arg('image' .. name) then
	      local image = p.add_file_prefix(arg('image' .. name))
	      local image_size = has_arg('image' .. name .. ' size') and arg('image' .. name .. ' size') or "200px" 
	      infobox
	        :tag('tr')
	          :tag('td')
	            :attr('style', 'text-align: center;')
	            :attr('colspan', '2')
		    	-- make sure it's the ogimage
	            :wikitext('[[main image::' .. image .. '| ]][[' .. image .. '|class=wikichip_ogimage|' .. image_size .. ']]')
	
	      -- add a caption, if provided
	      if has_arg('caption' .. name) then
	        infobox
	          :tag('tr')
	            :tag('td')
	            :attr('style', 'text-align: center;')
	              :attr('colspan', '2')
	              :wikitext('[[main image caption::' .. arg('caption' .. name) .. ']]')
	      end
		elseif not has_arg('no image' .. name) then
			if i == 1 then
		      infobox
		        :tag('tr')
		          :tag('td')
		            :attr('style', 'text-align: center;')
		            :attr('colspan', '2')
		            :wikitext('[[File:no photo (ic).svg|link=|200px]]')
	        end
	    end
	end


    -- ####################################################################
    -- some general info first
    p.add_separator(infobox, 'General Info')
    
    -- designer
    if has_arg('developer') then
      	local designers = mw.html.create('td'):attr('style', 'width: 99%;')
      	designers:wikitext('[[designer::' .. arg('developer') .. '| ]][[' .. arg('developer') .. ']]')
		for i = 2, 10 do
			if not has_arg('developer ' .. i) then break end
			designers:wikitext(', [[designer::' .. arg('developer ' .. i) .. '| ]][[' .. arg('developer ' .. i) .. ']]')
		end
   	  infobox:node(p.add_entry('Designer', designers))
	end
    
    -- manufacturer
    if has_arg('manufacturer') then
		local manufacturers = '[[manufacturer::' .. arg('manufacturer') .. '| ]][[' .. arg('manufacturer') .. ']]'
		for i = 2, 10 do
			if not has_arg('manufacturer ' .. i) then break end
			manufacturers = manufacturers .. ', [[manufacturer::' .. arg('manufacturer ' .. i) .. '| ]][[' .. arg('manufacturer ' .. i) .. ']]'
		end
		infobox:node(p.add_entry('Manufacturer', mw.html.create('td'):wikitext(manufacturers)))
	end
	
	-- release date
	if has_arg('first launched') or has_arg('first announced') then
	  local release = mw.html.create('td')
	  if has_arg('first announced') then
	    release:wikitext('[[first announced::' .. arg('first announced') .. ']] (announced)')
	  end
	  if has_arg('first launched') then
	  	if has_arg('first announced') then
	  	  release:wikitext('<br>')	
  		end
	    release:wikitext('[[first launched::' .. arg('first launched') .. ']] (launched)')
	  end
	  infobox:node(p.add_entry('Introduction', release))
	end
	
	if has_arg('fate') then
		infobox:node(p.add_entry('Fate', mw.html.create('td'):wikitext('[[fate::' .. arg('fate') .. ']]')))
	end
	
    -- ####################################################################
    -- some general info first
    p.add_separator(infobox, 'Microarchitecture')

	-- ISA
    if has_arg('isa') or has_arg('isa family') then
      local isa = mw.html.create('td'):wikitext('[[isa::' .. arg('isa') .. ']]')
      for i = 2, 10 do
      	if not has_arg('isa ' .. i) then break end
      	isa:wikitext(', [[isa::' .. arg('isa ' .. i) .. ']]')
      end
      if has_arg('isa family') then
        isa:wikitext('&nbsp;([[isa family::' .. arg('isa family') .. ']])')
  	  end
   	  infobox:node(p.add_entry('ISA', isa))
	end
	
	
	-- microarch
    if has_arg('microarch') then
      local microarchs = mw.html.create('td')
      microarchs:wikitext('[[microarchitecture::' .. arg('microarch') .. '| ]]')
      microarchs:wikitext('[[' .. mw.ustring.lower(arg('developer')) .. '/microarchitectures/' ..
      		mw.ustring.lower(arg('microarch')) .. '|' .. arg('microarch') .. ']]')
      for i = 2, 10 do
      	if not has_arg('microarch ' .. i) then break end
      	microarchs:wikitext(', [[microarchitecture::' .. arg('microarch ' .. i) .. '| ]]')
        microarchs:wikitext('[[' .. mw.ustring.lower(arg('developer')) .. '/microarchitectures/' ..
      		mw.ustring.lower(arg('microarch ' .. i)) .. '|' .. arg('microarch ' .. i) .. ']]')
      end
   	  infobox:node(p.add_entry('Microarchitecture', microarchs))
	end
	
	-- platform
	if has_arg('platform') then
	  infobox:node(p.add_entry('Platform', mw.html.create('td'):wikitext('[[platform::' .. arg('platform') .. ']]')))
	end
	
	-- chipset
    if has_arg('chipset') then
      local chipset = mw.html.create('td'):wikitext('[[chipset::' .. arg('chipset') .. ']]')
      for i = 2, 10 do
      	if not has_arg('chipset ' .. i) then break end
      	chipset:wikitext(', [[chipset::' .. arg('chipset ' .. i) .. ']]')
      end
   	  infobox:node(p.add_entry('Chipset', chipset))
	end
	
	-- word size
	if has_arg('word') then
	  infobox:node(p.add_entry('Word Size', mw.html.create('td'):wikitext('[[word size::' .. arg('word') .. '| ]]' .. arg('word'))))
	end
	
	-- process
    if has_arg('proc') then
      local process = mw.html.create('td'):wikitext('[[process::' .. arg('proc') .. ']]')
      for i = 2, 10 do
      	if not has_arg('proc ' .. i) then break end
      	process:wikitext(', [[process::' .. arg('proc ' .. i) .. ']]')
      end
   	  infobox:node(p.add_entry('Process', process))
	end
	
	-- Technology
	if has_arg('tech') then
	  infobox:node(p.add_entry('Technology', mw.html.create('td'):wikitext('[[technology::' .. arg('tech') .. ']]')))
	end
	
	-- Clock
	if has_arg('clock') then
	  infobox:node(p.add_entry('Clock', mw.html.create('td'):wikitext(arg('clock'))))
	elseif has_arg('clock min') then
	  infobox:node(p.add_entry('Clock', mw.html.create('td'):wikitext(arg('clock min') .. ' - ' .. arg('clock max'))))
	end
	
    -- ####################################################################
    -- ####################################################################
    -- Packaging
    local has_arg_pkg_name = has_arg('package name') or has_arg('package name 1')
    if has_arg('package module 1') or has_arg_pkg_name or has_arg('back image') then
        p.add_separator(infobox, 'Packaging')
    end

    -- Packaging
    if has_arg_pkg_name then
        local pdata = require('Module:packaging data')
        -- Also accept name, name 2, name 3 for consistency.
        local add_space = append_packaging_data(infobox, 'package name', pdata, false)
        for i = 1, 10 do
            add_space = append_packaging_data(infobox, 'package name ' .. i, pdata, add_space)
        end
    end

    if has_arg('package module 1') then
		for i = 1, 10 do
		    if has_arg('package module ' .. i) then
				infobox
					:tag('tr'):tag('td'):attr('colspan', '2'):attr('style', 'padding: 5px;')
					:wikitext(frame:preprocess(arg('package module ' .. i)))
			end
		end
	end

    -- back_image
	if has_arg('back image') then
		local back_image = p.add_file_prefix(arg('back image'))
		local back_image_size = has_arg('back image size') and arg('back image size') or "200px" 
		infobox
		:tag('tr')
		  :tag('td')
		    :attr('style', 'text-align: center;')
		    :attr('colspan', '2')
		    -- make sure it's the ogimage
		    :wikitext('[[' .. back_image .. '|link=|' .. back_image_size .. ']]')
		
		p.set_val('back image', back_image)
	end

    -- ####################################################################
    -- ####################################################################
    -- Successon
	if has_arg('successor') or has_arg('predecessor') then
		add_header(infobox, 'Succession')
		
		local s = infobox:tag('tr')
		local td = s:tag('td'):attr('colspan', '2')
		local d1 = td:tag('div'):attr('style', 'display: inline-flex;')
		local d2 = td:tag('div'):attr('style', 'display: inline-flex; float: right;')
		if has_arg('predecessor') then
			
		    local list
		    if has_arg('predecessor link') then
				list = '[[' .. arg('predecessor link') .. '|' .. arg('predecessor') .. ']]'
			else
				list = '[[' .. arg('predecessor') .. ']]'
			end
		    for i = 2, 10 do
		    	if not has_arg('predecessor ' .. i) then break end
		    	if has_arg('predecessor ' .. i .. ' link') then
		    		list = list .. '<br>[[' .. arg('predecessor ' .. i .. ' link') .. '|' .. arg('predecessor ' .. i) .. ']]'
	    		else
		    		list = list .. '<br>[[' .. arg('predecessor ' .. i) .. ']]'
    			end
			end
			
			d1:tag('div')
				:attr('style', 'float: left; padding-right: 10px; margin: auto 5px;')
				:wikitext('<i class="fa fa-chevron-left"></i>')
			d1:tag('div')
				:attr('style', 'float: left;')
				:wikitext(list)
		end
		if has_arg('successor') then
			local list
		    if has_arg('successor link') then
				list = '[[' .. arg('successor link') .. '|' .. arg('successor') .. ']]'
			else
				list = '[[' .. arg('successor') .. ']]'
			end
		    for i = 2, 10 do
		    	if not has_arg('successor ' .. i) then break end
		    	if has_arg('successor ' .. i .. ' link') then
		    		list = list .. '<br>[[' .. arg('successor ' .. i .. ' link') .. '|' ..
		    			arg('successor ' .. i) .. ']]'
	    		else
		    		list = list .. '<br>[[' .. arg('successor ' .. i) .. ']]'
    			end
			end
			
			d2:tag('div')
				:attr('style', 'float: left;')
				:wikitext(list)
			d2:tag('div')
				:attr('style', 'float: right; padding-left: 10px; margin: auto 5px;')
				:wikitext('<i class="fa fa-chevron-right"></i>')
		end
	end
    -- Contemporary
	if has_arg('contemporary') then
		add_header(infobox, 'Contemporary')
		
		local s = infobox:tag('tr')
		local td = s:tag('td'):attr('colspan', '2')
		
		td:attr('style', 'text-align: center;')

	    local list
	    if has_arg('contemporary link') then
			list = '[[' .. arg('contemporary link') .. '|' .. arg('contemporary') .. ']]'
		else
			list = '[[' .. arg('contemporary') .. ']]'
		end
	    for i = 2, 10 do
	    	if not has_arg('contemporary ' .. i) then break end
	    	if has_arg('contemporary ' .. i .. ' link') then
	    		list = list .. '<br>[[' .. arg('contemporary ' .. i .. ' link') .. '|' .. arg('contemporary ' .. i) .. ']]'
    		else
	    		list = list .. '<br>[[' .. arg('contemporary ' .. i) .. ']]'
			end
		end
		
		td:wikitext(list)
	end


	infobox:wikitext('[[instance of::core| ]]')
	infobox:wikitext('[[Category:all microprocessor cores]]')
	
    return infobox
end

return p