#!/usr/bin/ruby -w OPCODE_BITS = 12 UROM_BITS = 15 UIP_BITS_PER_OPCODE = UROM_BITS - OPCODE_BITS $stdout.write(< 8 $stdout.write("\t\t#{idx >> 3}.#{idx & 0x7}\t#{bit}\n") else $stdout.write("\t\t#{idx}\t#{bit}\n") end bitmap[bit] = 1 << idx proxy.define_singleton_method(bit) do if $this_uop $this_uop[name] |= 1 << idx else uop do $this_uop[name] |= 1 << idx end end end end proxy.instance_variable_set(:@bitmap, bitmap) instance_variable_set("@#{name}", proxy) end def urom_alias(urom, name, *bits) merged = 0 proxy = instance_variable_get("@#{urom}") bitmap = proxy.instance_variable_get(:@bitmap) throw "Name already in use" if bitmap.member?(name) bits.each do | bit | merged |= bitmap[bit] end bitmap[name] = merged proxy.define_singleton_method(name) do if $this_uop $this_uop[urom] |= merged else uop { $this_uop[urom] |= merged } end end proxy.instance_variable_set(:@bitmap, bitmap) end def inst(pattern, vector=false, &code) throw "nested instruction" if $this_inst throw "instruction with this pattern already defined" if $insts.member?(pattern) throw "too many opcodes" if $next_opcode > $next_vector $this_opnum = vector ? $next_vector : $next_opcode $stdout.write("\t#{$this_opnum.to_s(16)}\t#{($this_opnum << UIP_BITS_PER_OPCODE).to_s(16)}\t#{pattern}\n") $this_inst = [] code.call if not vector $eom ||= uip() uop { @decode.clear; @control.set_uip; constaddr($insts["!bom"] << UIP_BITS_PER_OPCODE) } end $this_inst.each_with_index do | uop, idx | uip = ($this_opnum << UIP_BITS_PER_OPCODE) + idx uop.each do | urom, entry | $uroms[urom][uip] = entry end end $insts[pattern] = $this_opnum $this_opnum = nil $this_inst = nil if vector $next_vector -= 1 else $next_opcode += 1 end end def vector(name, &code) inst("!#{name}", true, &code) end def uop(&code) throw "not in instruction" unless $this_inst throw "nested uop" if $this_uop throw "too many uops" if $this_inst.size >= (1 << UIP_BITS_PER_OPCODE) $this_uop = {} $uroms.each_key do | urom | $this_uop[urom] = 0 end code.call $this_inst << $this_uop $this_uop = nil end def const(value) throw "Value out of range" if value < 0 or value > 0xffff if $this_uop $this_uop[:consts] = value else uop do $this_uop[:consts] = value end end end def constaddr(value) const(value) @control.outaddr end def constdata(value) const(value) @control.outdata end def uip() throw "not in instruction" unless $this_inst return ($this_opnum << UIP_BITS_PER_OPCODE) + $this_inst.size end $stdout.write("Control wires:\n") load "modules.rb" $stdout.write("\nOpcodes:\n") load "vectors.rb" load "insts.rb" $stdout.write("\nWriting µrom contents:\n") $uroms.each do | urom, data | $stdout.write("\t#{urom}...") $stdout.flush if $urom_sizes[urom] > 8 0.upto(($urom_sizes[urom] / 8.0).ceil - 1) do | bank | $stdout.write(" #{bank}") $stdout.flush File.open("out/#{urom}.#{bank}.bin", "wb") do | fh | data.each do | word | fh.write(((word >> (8 * bank)) & 0xff).chr) end end end else File.open("out/#{urom}.bin", "wb") do | fh | data.each do | byte | fh.write(byte.chr) end end end $stdout.write("\n") end