From 60e1775b874015a3451e4bde10a8eb30701b1165 Mon Sep 17 00:00:00 2001 From: Julian Blake Kongslie Date: Tue, 6 Jul 2021 09:44:36 -0700 Subject: Initial commit. --- uasm.rb | 174 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100755 uasm.rb (limited to 'uasm.rb') diff --git a/uasm.rb b/uasm.rb new file mode 100755 index 0000000..c8a8967 --- /dev/null +++ b/uasm.rb @@ -0,0 +1,174 @@ +#!/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 -- cgit v1.2.3