- •Содержание
- •Часть 1. Описание схемы 4
- •Часть 2. Вспомогательное программное обеспечение. 7
- •Введение
- •Часть 1. Описание схемы Шинная организация
- •Иерархический принцип
- •Синхронизация
- •Система прерываний
- •Микрокомандное управление
- •Часть 2. Вспомогательное программное обеспечение. Ассемблер микрокоманд
- •Симулятор (модель) процессора
- •Литература
- •Приложение №1. Иерархия блоков эвм.
- •Приложение №2. Описание формата микрокоманд.
- •Приложение №3. Полный код микропрограммы.
- •Приложение №4. Исходный код ассемблера микрокоманд и сопутствующих утилит. Ассемблер микрокоманд
- •Утилитаmcd2mif
- •Утилитаlabelmap2mif
- •Приложение №5. Исходный код симулятора
Приложение №4. Исходный код ассемблера микрокоманд и сопутствующих утилит. Ассемблер микрокоманд
// BData.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace i8051
{
class Bit
{
byte fVal;
public Bit(byte b)
{
if (b > 1) throw new FormatException("Bit data format error!");
fVal = b;
}
public static implicit operator Bit(byte b)
{
return new Bit(b);
}
public static implicit operator Bit(int b)
{
return new Bit(Convert.ToByte(b));
}
public static implicit operator byte(Bit b)
{
return b.fVal;
}
public static implicit operator bool(Bit b)
{
return b.fVal > 0;
}
public static implicit operator Bit(bool b)
{
return new Bit(Convert.ToByte(b));
}
public override string ToString()
{
return fVal == 0 ? "0" : "1";
}
public void Set()
{
fVal = 1;
}
public void Clear()
{
fVal = 0;
}
}
class BData
{
Bit[] Bits;
int fCount;
int Length { get { return fCount; } }
public BData(int Count, Int64 Data)
{
fCount = Count;
Bits = new Bit[fCount];
for (int i = 0; i < fCount; i++)
{
Bits[i] = (byte)(Data % 2);
Data /= 2;
}
}
long GetNum()
{
int Result = 0;
for (int i = fCount-1; i >= 0; i--)
{
Result *= 2;
Result += Bits[i];
}
return Result;
}
#region ImplictByte
public static implicit operator BData(byte b)
{
return new BData(8, b);
}
public static implicit operator byte(BData b)
{
return (byte)b.GetNum();
}
#endregion
#region ImplictInt
public static implicit operator BData(int b)
{
return new BData(32, b);
}
public static implicit operator int(BData b)
{
return (int)b.GetNum();
}
#endregion
#region ImplictLong
public static implicit operator BData(long b)
{
return new BData(64, b);
}
public static implicit operator long(BData b)
{
return b.GetNum();
}
#endregion
public Bit this[int x]
{
get
{
if (x >= fCount || x < 0) throw new TypeAccessException("Invalid bit!");
return new Bit(Bits[x]);
}
set
{
if (x >= fCount || x < 0) throw new TypeAccessException("Invalid bit!");
Bits[x] = (byte)value;
}
}
public BData this[int From, int To]
{
get
{
if (From > To) { int t = From; From = To; To = t; }
if ((From >= fCount || From < 0) || (To >= fCount || To < 0)) throw new TypeAccessException("Invalid bit!");
BData Result = new BData(To - From + 1, 0);
for (int i = 0; i <= To - From; i++)
{
Result[i] = this[i + From];
}
return Result;
}
set
{
if (From > To) { int t = From; From = To; To = t; }
if ((From >= fCount || From < 0) || (To >= fCount || To < 0)) throw new TypeAccessException("Invalid bit!");
for (int i = 0; i <= To - From; i++)
{
this[i + From] = value[i];
}
}
}
public /*override*/ string ToString()
{
string S = "";
for (int i = 0; i < Bits.Length; i++)
{
S += Bits[i];
}
return S;
}
}
}
//
// i8051 microcode assembler
// Part of sci-reserching project at "Organisation of ECM"
// (C) C.c 2010 via gnu gpl
//
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using i8051;
namespace i8051_mc_compiler
{
static class ArgConv
{
public static int Do(string a)
{
if (a.ToUpper().StartsWith("0X")) // hex
{
return int.Parse(a.Substring(2), System.Globalization.NumberStyles.HexNumber);
}
if (a.ToUpper().EndsWith("H")) // hex
{
return int.Parse(a.Substring(0, a.Length - 2), System.Globalization.NumberStyles.HexNumber);
}
if (a.ToUpper().EndsWith("B")) // bin
{
int res = 0;
for (int i = 0; i < a.Length - 1; i++)
{
res *= 2;
res += Convert.ToInt32(a[i] + "");
}
return res;
}
if (a.ToUpper().EndsWith("O")) // oct
{
int res = 0;
for (int i = 0; i < a.Length - 1; i++)
{
res *= 8;
res += Convert.ToInt32(a[i] + "");
}
return res;
}
return int.Parse(a);
}
}
class MCBlock
{
string fName;
int fBytes;
public BData Code;
public string Name { get { return fName; } }
public int Bytes { get { return fBytes; } }
public MCBlock(string Name, int Bytes)
{
fName = Name;
fBytes = Bytes;
Code = 0;
}
public void Reset()
{
Code = 0;
}
}
abstract class MCField
{
abstract public void Set(string Val);
abstract public string Name { get; }
}
class FlagField : MCField
{
string fName;
int fBit;
public MCBlock Block;
public override string Name { get { return fName; } }
public int Bit { get { return fBit; } }
public FlagField(string Name, int Bit, MCBlock Block)
{
this.Block = Block;
fName = Name;
fBit = Bit;
}
public override void Set(string S)
{
Block.Code[fBit] = 1;
}
}
class EnumField : MCField
{
string fName;
int fBitBeg, fBitEnd;
public MCBlock Block;
public override string Name { get { return fName; } }
string[] fEnum;
public EnumField(string Name, int BitBeg, int BitEnd, string Enum, MCBlock Block)
{
this.Block = Block;
fName = Name;
fEnum = Enum.Split(',');
fBitBeg = BitBeg;
fBitEnd = BitEnd;
}
public override void Set(string Val)
{
for (int i = 0; i < fEnum.Length; i++ )
if (fEnum[i].ToUpper() == Val.ToUpper())
{
Block.Code[fBitBeg, fBitEnd] = i;
return;
}
throw new Exception(String.Format("Incorrect value - \"{0}\" for \"{1}\" field!", Val, fName));
}
}
class ImmediateFiled : MCField
{
string fName;
int fBeg;
int fEnd;
MCBlock Block;
public override string Name
{
get { return fName; }
}
public override void Set(string Val)
{
Block.Code[fBeg, fEnd] = ArgConv.Do(Val);
}
public ImmediateFiled(string Name, int BegBit, int EndBit, MCBlock Block)
{
fName = Name;
fBeg = BegBit;
fEnd = EndBit;
this.Block = Block;
}
}
class Program
{
static List<MCBlock> MCBlocks = new List<MCBlock>();
static MCBlock Control, Alu, DataSfr, CodeXData, Bit, Const, __If;
static void InitBlocks()
{
Control = new MCBlock("Control", 2); MCBlocks.Add(Control);
__If = new MCBlock("If", 1); MCBlocks.Add(__If);
Alu = new MCBlock("Alu", 1); MCBlocks.Add(Alu);
DataSfr = new MCBlock("DataSfr", 4); MCBlocks.Add(DataSfr);
CodeXData = new MCBlock("CodeXData", 2); MCBlocks.Add(CodeXData);
Bit = new MCBlock("Bit", 1); MCBlocks.Add(Bit);
Const = new MCBlock("Const", 2); MCBlocks.Add(Const);
}
static List<MCField> Fields = new List<MCField>();
static void InitFields()
{
// Control
Fields.Add(new FlagField("ROMM++", 0, Control));
Fields.Add(new FlagField("SetInstruction", 1, Control));
Fields.Add(new FlagField("Goto", 2, Control));
Fields.Add(new ImmediateFiled("ROMM", 3, 12, Control));
// interrupts
Fields.Add(new FlagField("ClrIntFlag", 13, Control));
Fields.Add(new FlagField("EndInterrupt", 14, Control));
Fields.Add(new FlagField("IPCL->BusB", 15, Control));
// If
Fields.Add(new EnumField("If", 0, 4, "True,PSW.CF,PSW.OF,PSW.AF,WRK1.0,WRK1.1,WRK1.2,WRK1.3,WRK1.4,WRK1.5,WRK1.6,WRK1.7,ALU.CF,ALU.OF,ALU.AF,Wrk1Z,!IntrFlag", __If));
// Alu
Fields.Add(new FlagField("BusB->RA", 0, Alu));
Fields.Add(new FlagField("BusC->RB", 1, Alu));
Fields.Add(new FlagField("+Psw.cf", 2, Alu));
Fields.Add(new FlagField("-Psw.cf", 2, Alu));
Fields.Add(new FlagField("Alu->BusB", 3, Alu));
Fields.Add(new FlagField("AluPsw->BusB", 4, Alu));
Fields.Add(new EnumField("AluOp", 5, 7, "res,suba,subb,add,xor,or,and,set", Alu));
// CodeXData
Fields.Add(new FlagField("BusB->XData[ACX]", 3, CodeXData));
Fields.Add(new FlagField("BusB->PCL", 4, CodeXData));
Fields.Add(new FlagField("BusC->PCH", 5, CodeXData));
Fields.Add(new FlagField("PC++", 6, CodeXData));
Fields.Add(new FlagField("Alu->BusB", 3, CodeXData));
Fields.Add(new EnumField("BusB16", 7, 9, "Null,Code,XData,PCH,PCL,DPH,DPL,Null", CodeXData));
Fields.Add(new EnumField("BusC16", 10, 12, "Null,Code,XData,PCH,PCL,DPH,DPL,APCH", CodeXData));
Fields.Add(new EnumField("ACX", 13, 14, "PC,DPTR,Wrk2.Wrk1", CodeXData));
// DataSfr
Fields.Add(new FlagField("BusB->Data[BusA]", 0, DataSfr));
Fields.Add(new FlagField("BusB->Acc", 1, DataSfr));
Fields.Add(new FlagField("BusB->B", 2, DataSfr));
Fields.Add(new FlagField("BusB->SP", 3, DataSfr));
Fields.Add(new FlagField("SP++", 4, DataSfr));
Fields.Add(new FlagField("SP--", 5, DataSfr));
Fields.Add(new FlagField("BusB->PSW", 6, DataSfr));
Fields.Add(new FlagField("DPTR++", 7, DataSfr));
Fields.Add(new FlagField("BusB->DPL", 8, DataSfr));
Fields.Add(new FlagField("BusB->DPH", 9, DataSfr));
Fields.Add(new EnumField("BusB8", 10, 13, "Null,Wrk2,Wrk1,DPH,DPL,PSW,Data[BusA],SP,B,PswRLC,PswRRC,AccRLC,AccRRC,AccRR,AccRL,Acc", DataSfr));
Fields.Add(new FlagField("SetWrk1", 14, DataSfr));
Fields.Add(new FlagField("SetWrk2", 15, DataSfr));
Fields.Add(new EnumField("Wrk1Src", 16, 16, "BusB,BusC", DataSfr));
Fields.Add(new EnumField("Wrk2Src", 17, 17, "BusB,BusC", DataSfr));
Fields.Add(new EnumField("BusC8", 18, 21, "Null,Wrk2,Wrk1,Null,Null,Null,Null,Null,Null,Null,Null,Null,AccSwap,Acc,CRPsw,CR", DataSfr));
Fields.Add(new EnumField("BusA", 22, 24, "Null,AdBit,Bank+IR[2..0],Bank+IR[0],Acc,Wrk2,Wrk1,SP", DataSfr));
Fields.Add(new FlagField("MulAB", 25, DataSfr));
Fields.Add(new FlagField("DivAB", 26, DataSfr));
Fields.Add(new FlagField("MulPsw->BusB", 27, DataSfr));
Fields.Add(new FlagField("DivPsw->BusB", 28, DataSfr));
// Const
Fields.Add(new ImmediateFiled("BusBC", 0, 7, Const));
Fields.Add(new ImmediateFiled("BusCC", 8, 15, Const));
// Bit
Fields.Add(new FlagField("BusB->AdBit", 0, Bit));
Fields.Add(new FlagField("BusB->BitBuf", 1, Bit));
Fields.Add(new FlagField("!Bit", 2, Bit));
Fields.Add(new FlagField("BLU->BusB", 3, Bit));
Fields.Add(new EnumField("BitOp", 4, 6, "Null,Equal,Not,And,Or,Xor,Set,Set", Bit));
}
static string ProcessInstruction(string Line)
{
foreach (MCBlock Block in MCBlocks)
{
Block.Reset();
}
string[] MCOps = Line.Split(';');
foreach (string _MCOp in MCOps)
{
string MCOp = _MCOp;
if (MCOp == "") continue;
if (MCOp.Contains('@'))
{
int At = MCOp.IndexOf('@');
string Label = MCOp.Substring(At);
if (!Labels.ContainsKey(Label.ToUpper())) throw new Exception(String.Format("Label not found - {0}(line {1})", Label, nLine));
MCOp=MCOp.Remove(At);
MCOp = MCOp + Labels[Label.ToUpper()];
}
string[] sMCOp = MCOp.Split('=');
bool Found = false;
foreach (MCField Field in Fields)
{
if (Field.Name.ToUpper() == sMCOp[0].ToUpper())
{
string Val;
try { Val = sMCOp[1]; }
catch (Exception e) { Val = ""; }
Field.Set(Val);
Found = true;
}
}
if (!Found) throw new Exception(String.Format("Unknown field - {0}(line {1})", sMCOp[0], nLine));
}
string Res = "";
foreach (MCBlock Block in MCBlocks)
{
Res+=String.Format("{0:X" + Block.Bytes*2 + "}|", (int)Block.Code);
}
return Res;
}
static int nLine = 0;
static int ROMM = 0;
static Dictionary<string, int> Labels = new Dictionary<string,int>();
static string ProcessLine(string Line)
{
Line = Line.Split('#')[0];
string sLine = "";
foreach (string s in Line.Split(' ')) sLine += s;
return sLine;
}
static void PassOne(string[] Source)
{
nLine = 0;
ROMM = 0;
Labels.Clear();
foreach (string Line in Source)
{
nLine++;
string sLine = ProcessLine(Line);
while (sLine != "")
{
if (sLine.StartsWith("@"))
{
string Label = sLine.Split(':')[0];
if (sLine.Split(':').Length > 1) sLine = sLine.Split(':')[1];
else sLine = "";
Labels.Add(Label.ToUpper(), ROMM);
Console.WriteLine("Label {0} at 0x{1:x3}", Label, ROMM);
}
else
{
ROMM++;
sLine = "";
}
}
}
}
static List<string> PassTwo(string[] Source)
{
nLine = 0;
ROMM = 0;
List<string> Result = new List<string>();
Result.Add(Convert.ToString(MCBlocks.Count));
for (int i = 0; i < MCBlocks.Count; i++)
{
Result.Add(String.Format("{0} {1} {2}", i, MCBlocks[i].Bytes, MCBlocks[i].Name));
}
foreach (string Line in Source)
{
nLine++;
string sLine = ProcessLine(Line);
while (sLine != "")
{
if (sLine.StartsWith("@"))
{
string Label = sLine.Split(':')[0];
if (sLine.Split(':').Length > 1) sLine = sLine.Split(':')[1];
else sLine = "";
}
else
{
Result.Add(ProcessInstruction(sLine));
ROMM++;
sLine = "";
}
}
}
return Result;
}
static void WriteLabels(string FName)
{
StreamWriter LabelMap = File.CreateText(FName);
foreach (string Key in Labels.Keys)
{
LabelMap.WriteLine("{0}:{1:X3}", Key, Labels[Key]);
}
LabelMap.Close();
}
static void Main(string[] args)
{
Console.WriteLine("BloodEye microcode assembler for i8051");
Console.WriteLine("(C) C.c 2011\n");
InitBlocks();
InitFields();
if (args.Length < 1)
{
Console.WriteLine("Error: no input file specified!");
return;
}
string fname = args[0];
List<string> Source;
try
{
Source = System.IO.File.ReadAllLines(args[0]).ToList();
}
catch (Exception e)
{
Console.WriteLine("Error: Can't open file \""+ fname +"\"");
return;
}
Console.WriteLine(String.Format("Processing file \"{0}\" ({1} lines, {2} bytes)\n", fname, Source.Count, System.IO.File.Open(fname, System.IO.FileMode.Open).Length));
try
{
Console.WriteLine("Pass one...");
PassOne(Source.ToArray());
Console.WriteLine();
Console.WriteLine("Pass two...");
List<string> Output = PassTwo(Source.ToArray());
Console.WriteLine();
Console.WriteLine("Writing labelmap...");
WriteLabels(fname + ".labelmap");
File.WriteAllLines(fname + ".mcd", Output.ToArray());
Console.WriteLine("Done.\n");
}
catch (Exception e)
{
Console.WriteLine("Error: "+e.Message);
}
}
}
}