diff --git a/software/arci/arcigen.py b/software/arci/arcigen.py new file mode 100755 index 0000000..0389827 --- /dev/null +++ b/software/arci/arcigen.py @@ -0,0 +1,328 @@ +#!/usr/bin/python3 +""" +© IBM Corp. 2020 +Licensed under the Apache License, Version 2.0 (the "License"), as modified by the terms below; you may not use the files in this +repository except in compliance with the License as modified. +You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Modified Terms: + + 1) For the purpose of the patent license granted to you in Section 3 of the License, the "Work" hereby includes implementations of + the work of authorship in physical form. + + 2) Notwithstanding any terms to the contrary in the License, any licenses necessary for implementation of the Work that are available + from OpenPOWER via the Power ISA End User License Agreement (EULA) are explicitly excluded hereunder, and may be obtained from OpenPOWER + under the terms and conditions of the EULA. + +Unless required by applicable law or agreed to in writing, the reference design distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. + +Additional rights, including the ability to physically implement a softcore that is compliant with the required sections of the Power +ISA Specification, are available at no cost under the terms of the OpenPOWER Power ISA EULA, which can be obtained (along with the Power +ISA) here: https://openpowerfoundation.org. + +Brief explanation of modifications: + +Modification 1: This modification extends the patent license to an implementation of the Work in physical form – i.e., +it unambiguously permits a user to make and use the physical chip. + +Modification 2: This modification clarifies that licenses for the Power ISA are provided via the (royalty-free) Power ISA EULA, +and not under this license. To prevent fragmentation of the Power ISA, the Power ISA EULA requires that Power ISA Cores be +licensed consistent with the terms of the Power ISA EULA. By ensuring that rights available via the Power ISA EULA are received +under (and subject to) the EULA, this consistency is maintained in accordance with the terms of the EULA. Any necessary additional +licenses for the specific Power ISA Core are granted under this modified Apache license. +""" + +from types import MethodType +from ctypes import c_uint32 +import time + +# set up + +header = """ +* arci v.0.0001 +* ----------------------------------------------------------------------------------------- +""" +header += f'* Generated: {time.strftime("%b %d %Y %I:%M:%S %p %Z", time.gmtime())}\n' +header += '*\n' + +# ------------------------------------------------------------------------------------------------- +# Classes + +class Fac: + + def __init__(self, name, value=None, spr=False, gpr=False, fpr=False, vsr=False): + self.name = name + self.value = value + self.spr = spr + self.gpr = gpr + self.fpr = fpr + self.vsr = vsr + self.ref = False + self.chg = False + facs[name] = self + + def comment(self): + return '' + + def print(self): + lines.append(f'R {self.name:6} {self.value:08X}') + + +class Op: + + def __init__(self, name): + self.name = name + ops[name] = self + + def fmt(self, val): + return f'{val:08X}' + + def se16(self, v): + v = v & 0xFFFF + if v > 0x7FFF: + v = 0xFFFF0000 + v + return v + +# probs make different Op versions for different formats +class Addi(Op): + + def __init__(self): + self.name = 'addi' + + def do(self, rt, ra, v): + self.rt = rt + self.ra = ra + self.imm = v + v = self.se16(v) + if ra == "R00": + res = c_uint32(v).value + else: + res = c_uint32(c_uint32(gpr[ra].value).value + v).value + gpr[rt].value = res + self.cia = cia.value + cia.value += 4 + self.nia = cia.value + if ra != "R00": + gpr[ra].ref = True + gpr[rt].chg = True + cia.chg = True + self.res = [(rt, gpr[rt].value, gpr[rt].comment()),(cia.name, self.nia, cia.comment())] + return self + + def print(self): + lines.append(f'I {self.cia:08X} {self.name:10s} {self.rt},{self.ra},{self.imm}') + for i in range(len(self.res)): + lines.append(f'R {self.res[i][0]:6} {self.res[i][1]:08X} {self.res[i][2]}') + lines.append('') + return self + +class Add(Op): + + def __init__(self): + self.name = 'add' + + def do(self, rt, ra, rb): + self.rt = rt + self.ra = ra + self.rb = rb + res = c_uint32(c_uint32(gpr[ra].value).value + c_uint32(gpr[rb].value).value).value + gpr[rt].value = res + self.cia = cia.value + cia.value += 4 + self.nia = cia.value + gpr[ra].ref = True + gpr[rb].ref = True + gpr[rt].chg = True + cia.chg = True + self.res = [(rt, gpr[rt].value, gpr[rt].comment()),(cia.name, self.nia, cia.comment())] + return self + + def print(self): + lines.append(f'I {self.cia:08X} {self.name:10s} {self.rt},{self.ra},{self.rb}') + for i in range(len(self.res)): + lines.append(f'R {self.res[i][0]:6} {self.res[i][1]:08X} {self.res[i][2]}') + lines.append('') + return self + +class Add_R(Op): + + def __init__(self): + self.name = 'add.' + + def do(self, rt, ra, rb): + self.rt = rt + self.ra = ra + self.rb = rb + res = c_uint32(c_uint32(gpr[ra].value).value + c_uint32(gpr[rb].value).value).value + gpr[rt].value = res + if res == 0: + cr0 = 0x2 + elif res < 0: + cr0 = 0x8 + else: + cr0 = 0x4 + cr0 = cr0 | xer.so() + cr.value = (cr.value & 0x00FFFFFF) | (cr0 << 28) + self.cia = cia.value + cia.value += 4 + self.nia = cia.value + gpr[ra].ref = True + gpr[rb].ref = True + gpr[rt].chg = True + cr.chg = True + cia.chg = True + self.res = [(rt, gpr[rt].value,gpr[rt].comment()), (cr.name, cr.value, cr.comment()), (cia.name, self.nia, cia.comment())] + return self + + def print(self): + lines.append(f'I {self.cia:08X} {self.name:10s} {self.rt},{self.ra},{self.rb}') + for i in range(len(self.res)): + lines.append(f'R {self.res[i][0]:6} {self.res[i][1]:08X} {self.res[i][2]}') + lines.append('') + return self + +# ------------------------------------------------------------------------------------------------- +# Helpers + +# def: print if nonzero +# all=True: print all +# ref=True: print only if referenced +# chg=True: print only if changed + +def printSPR(all=False, ref=None, chg=None): + for k,f in facs.items(): + if f.spr: + n = f.name + v = f.value + c = f.comment() + if all or (v != 0 and ref is None and chg is None) or (ref is not None and f.ref == ref) or (chg is not None and f.chg == chg): + lines.append(f'R {n:6} {v:08X} {c}') + + +def printRegs(all=False, ref=None, chg=None): + for i in range(32): + n = f'R{i:02}' + g = gpr[n] + v = g.value + c = g.comment() + if all or (v != 0 and ref is None and chg is None) or (ref is not None and g.ref == ref) or (chg is not None and g.chg == chg): + lines.append(f'R {n:6} {v:08X} {c}') + +def printTest(): + + for i in range(len(lines)): + print(lines[i]) + +# ------------------------------------------------------------------------------------------------- +# Create facs and aliases + +lines = [] +facs = {} +ops = {} + +cia = Fac('CIA', 0x120000, spr=True) + +def commentCR(self): + c = '* ' + x = f'{self.value:08X}' + for i in range(8): + c += f'F{i}:{x[i]} ' + return c + +cr = Fac('CR', 0, spr=True) +cr.comment = MethodType(commentCR, cr) + +def xerSO(self): + return (self.value & 0x80000000) >> 31 + +xer = Fac('XER', 0, spr=True) +xer.so = MethodType(xerSO, xer) + +srr0 = Fac('SRR0', 0, spr=True) +srr1 = Fac('SRR1', 0, spr=True) +dar = Fac('DAR', 0, spr=True) +dsisr = Fac('DSISR',0, spr=True) + +# probs some trick +r0 = 'R00' +r1 = 'R01' +r2 = 'R02' +r3 = 'R03' +r4 = 'R04' +r5 = 'R05' +r6 = 'R06' +r7 = 'R07' +r8 = 'R08' +r9 = 'R09' +r10 = 'R10' +r11 = 'R11' +r12 = 'R12' +r13 = 'R13' +r14 = 'R14' +r15 = 'R15' +r16 = 'R16' +r17 = 'R17' +r18 = 'R18' +r19 = 'R19' +r20 = 'R20' +r21 = 'R21' +r22 = 'R22' +r23 = 'R23' +r24 = 'R24' +r25 = 'R25' +r26 = 'R26' +r27 = 'R27' +r28 = 'R28' +r29 = 'R29' +r30 = 'R30' +r31 = 'R31' + +gpr = {} +def commentGPR(self): + return f'* {self.value:10}' + +for i in range(32): + name = f'R{i:02}' + gpr[name] = Fac(name, 0, gpr=True) + gpr[name].comment = MethodType(commentGPR, gpr[name]) + +# ------------------------------------------------------------------------------------------------- +# Create ops + +cia.ref = True +addi = Addi() +add = Add() +add_r = Add_R() + +# ------------------------------------------------------------------------------------------------- +# Do something + +lines.append(header) + +lines.append('* Initialization\n') +printSPR(all=True) +printRegs(all=True) + +lines.append('\n* Instructions\n') + +# phony dumb test +addi.do(r3,r3,1).print() +addi.do(r3,r3,1).print() +addi.do(r3,r3,1).print() +addi.do(r4,r0,-3).print() +add_r.do(r4,r4,r3).print() + +lines.append('\n* Results (Changed)\n') +printSPR(chg=True) +printRegs(chg=True) + +lines.append('\n* Results\n') +printSPR(all=True) +printRegs(all=True) + +# create .tst file +# create .s file +# create .o file (or two, one the test, one the test+runner) +printTest() \ No newline at end of file diff --git a/software/arci/simple.tst b/software/arci/simple.tst index bcd58d4..e0612ea 100644 --- a/software/arci/simple.tst +++ b/software/arci/simple.tst @@ -1,13 +1,120 @@ -* Simple test + +* arci v.0.0001 +* ----------------------------------------------------------------------------------------- +* Generated: Nov 03 2021 06:00:25 PM GMT +* * Initialization -R R1 00000001 +R CIA 00120000 +R CR 00000000 * F0:0 F1:0 F2:0 F3:0 F4:0 F5:0 F6:0 F7:0 +R XER 00000000 +R SRR0 00000000 +R SRR1 00000000 +R DAR 00000000 +R DSISR 00000000 +R R00 00000000 * 0 +R R01 00000000 * 0 +R R02 00000000 * 0 +R R03 00000000 * 0 +R R04 00000000 * 0 +R R05 00000000 * 0 +R R06 00000000 * 0 +R R07 00000000 * 0 +R R08 00000000 * 0 +R R09 00000000 * 0 +R R10 00000000 * 0 +R R11 00000000 * 0 +R R12 00000000 * 0 +R R13 00000000 * 0 +R R14 00000000 * 0 +R R15 00000000 * 0 +R R16 00000000 * 0 +R R17 00000000 * 0 +R R18 00000000 * 0 +R R19 00000000 * 0 +R R20 00000000 * 0 +R R21 00000000 * 0 +R R22 00000000 * 0 +R R23 00000000 * 0 +R R24 00000000 * 0 +R R25 00000000 * 0 +R R26 00000000 * 0 +R R27 00000000 * 0 +R R28 00000000 * 0 +R R29 00000000 * 0 +R R30 00000000 * 0 +R R31 00000000 * 0 + +* Instructions + +I 00120000 addi R03,R03,1 +R R03 00000001 * 1 +R CIA 00120004 + +I 00120004 addi R03,R03,1 +R R03 00000002 * 2 +R CIA 00120008 + +I 00120008 addi R03,R03,1 +R R03 00000003 * 3 +R CIA 0012000C + +I 0012000C addi R04,R00,-3 +R R04 FFFFFFFD * 4294967293 +R CIA 00120010 + +I 00120010 add. R04,R04,R03 +R R04 00000000 * 0 +R CR 20000000 * F0:2 F1:0 F2:0 F3:0 F4:0 F5:0 F6:0 F7:0 +R CIA 00120014 + -* Test +* Results (Changed) -I 00001000 38210001 addi r1,r1,1 +R CIA 00120014 +R CR 20000000 * F0:2 F1:0 F2:0 F3:0 F4:0 F5:0 F6:0 F7:0 +R R03 00000003 * 3 +R R04 00000000 * 0 * Results -R R1 00000002 * do you has opulence or are you worthless and weak? +R CIA 00120014 +R CR 20000000 * F0:2 F1:0 F2:0 F3:0 F4:0 F5:0 F6:0 F7:0 +R XER 00000000 +R SRR0 00000000 +R SRR1 00000000 +R DAR 00000000 +R DSISR 00000000 +R R00 00000000 * 0 +R R01 00000000 * 0 +R R02 00000000 * 0 +R R03 00000003 * 3 +R R04 00000000 * 0 +R R05 00000000 * 0 +R R06 00000000 * 0 +R R07 00000000 * 0 +R R08 00000000 * 0 +R R09 00000000 * 0 +R R10 00000000 * 0 +R R11 00000000 * 0 +R R12 00000000 * 0 +R R13 00000000 * 0 +R R14 00000000 * 0 +R R15 00000000 * 0 +R R16 00000000 * 0 +R R17 00000000 * 0 +R R18 00000000 * 0 +R R19 00000000 * 0 +R R20 00000000 * 0 +R R21 00000000 * 0 +R R22 00000000 * 0 +R R23 00000000 * 0 +R R24 00000000 * 0 +R R25 00000000 * 0 +R R26 00000000 * 0 +R R27 00000000 * 0 +R R28 00000000 * 0 +R R29 00000000 * 0 +R R30 00000000 * 0 +R R31 00000000 * 0