Fleranvändar-FORTH på FCPU Paul Svensson Inge Wallin LYSATOR, LiTH I den här artikeln beskriver vi hur vi hade tänkt oss den FORTH som blir nästa steg efter det som finns nu. Den nuvarande FORTHen är bara för en användare, men nästa skall bli ett komplett fleranvändarsystem! Lysator har en unik maskin, en FCPU från DataSAAB. Den är den enda sitt slag i världen. Därför existera ytterst lite mjukvara till den, t ex så finns det inget operativsystem. Pga detta har FCPUn stått mer eller mindre stilla genom åren. Nu har den dock börjat användas i och med att Paul Svensson har hackat ihop en FORTH till den. Denna FORTH, som är ganska primitiv, har varit ett test inför den egentliga uppgiften: att skriva ett fler användarsystem. Att det blev just FORTH beror på att det språket ha rykte om sig att vara extrem lättimplementerat. Det skulle alltså borga för att det hela inte blev ännu ett oavslutat projekt. När Lysator omstartades 1984 döpte FCPUn till Cecilia och planerna på FORTH började ta fast form. Efter som maskinen saknade vettigt I/C beslöt vi att först bygga ett terminalkort. Paul och Krister (Joas) satte hösten -85 igång ett projekt i kursen digital konstruktion, som skulle innehålla bl a åtta terminalsnören. Det hela drog dock ut på tiden (lumpen kom emellan), men i januari i år började kortet bli färdigt. När vi funderade på vad vi skulle hacka ihop för att demonstrera kortets funktion föddes iden med mikroFORTH, dvs en FORTH som exekverar helt och hållet i mikrokodsminnet. Att skriva en FORTH visade sig till] och med vara enklare än väntat. Trots näst intill inga tidigare erfarenheter av språket tog det bara två veckor från ide till fungerande system! Sedan dess har mikro-FORTHen vidareutvecklats, och den innehåller nu drygt trehundra ord. Ett trettiotal av dessa är skrivna direkt i mikrokod, resten i FORTH. Vi använder också en av terminalledningarna till att föra över diskblock till och från Lysators ABC1600, Ingrid, då Cecilia saknar egna sekundärminnen. Mikro-FORTHen är dock ganska begränsad, eftersom vi inte ville använda mer hårdvara än absolut nödvändigt. Det visade sig möjligt att skriva systemet så att bara CU och CS (ett halvt skåp av fyra) behövde användas. Resten av maskinen behöver inte ens vara strömsatt. När man skall bygga ett fleranvändarsystem kan man naturligtvis inte begränsa sig på det viset. Man bör i stället sträva efter att utnyttja hela maskinens kapacitet. För att ge en inblick i vad FCPUn klarar av kommer här en kort beskrivning: att FCPUn består, som den minnesgode läsaren redan vet, av tre delar: CU, AU och FU. CU (Control Unit) är den styrande delen där mikrokodstolken ligger. Den är ansluten till det skrivbara mikrokodsminnet (CS = Control Storage). I CU finns också statusbitar för hela maskinen, en 16-bitars ALU, några register, realtidsklockor, mm. Dessa delar, som är skuggade i figuren ovan, är de enda som utnyttjas i mikro-FORTH. AU (Arithmetic Unit) innehåller ett antal register och en 64-bitars ALU. ALUn ingår som ett litet kuriosum en 64-bitars barrel-shifter. FU (Field access Unit) är kort sagt gränsnittet till maskinens internminne. Minnet uppgår f n till 512 KByte vilket fyller två skåp, men kan bygga ut till 2 MByte. Detta väntas uppta ett kort. FU kan läsa och skriva ord av 18 bytes längd i minnet, oberoende av ordgränser. Den har dessutom en handfull register som kan räknas upp eller ner på ett enkelt sätt. En intressant detalj med FCPUn är att dessa delar kan arbeta parallellt. Man kan alltså ha flera mikroinstruktioner under exekvering samtidigt (max 4). Därför blir en FORTH som utnyttjar alla delar snabbare än den nuvarande. En annan uppsnabbande faktor är att de olika delarna utnyttjas till det som de är gjorda för. I mikro-FORTHen är t ex ett högerskift implementerat i mikro-ALUn en bit åt gången. När vi kan utnyttja AUn så får vi hela skiftningen gjord med en instruktion. FORTHs sätt att arbeta I FORTH arbetar man hela tiden mot en stack. Alla aritmetiska och logiska funktioner tar sina argument från stacken och lägger sina resultat där. Dessutom finns ett antal ord som har som sin enda uppgift att manipulera stacken. Denna stack kallas datastacken. FORTH är ju ett programmeringsspråk. Det behövs alltså en plats där man kan lagra returadresser som uppkommer genom proceduranrop. Det är naturligtvis möjligt att lagra dessa tillsammans med de andra data på datastacken; det är så som t ex PASCAL fungerar, men i FORTH har man valt ett lite annorlunda sätt att se på saken, och har alltså två stackar. Den andra stacken kallas för returstacken. Båda dessa stackar har var sin stackpekare som av tradition kallas SP (Stack Pointer) och RP (Return stack Pointer). Ett tredje viktigt register är instruktionspekaren, IP. Ett program i FORTH består av ett antal FORTHord, eller kortare ord. Alla ord finns lagrade i en ordlista. Här finns data om hur ordet skall användas samt definitionen av ordet. Definitionen av ett ord består uteslutande av en serie adresser. På dessa adresser finns andra ord och när man kör sitt program kommer underorden att i sin tur exekveras. Längst ned finns ord skrivna i mikrokod. Alla ord lagras i en ordlista. I multi-FORTH är ordlistan implementeras som en länkad lista där huvudet till varje element ser ut så här: Lång länk (om kort länk =o) (24 bitar) Kort länk till föregående ord (8 bitar) Statusbyte för ordet (8 bitar) immediate ( 1 bit) smudge ( 1 bit) reserv ( 1 bit) längd på namnet ( 5 bitar) Namnet (max 31 byte) Kodpekare (8 bitar) Efter huvudet följer relevanta data för respektive ord. Länken till föregående ord är normalt bara ett åtta bitars offset, men eftersom detta inte räcker om man behöver en lång länk, så finns möjligheten att använda en 24 bitarsadress som länk. Den korta länken är då 0. Immediatebiten talar om ifall ordet skall exekveras även vid kompilering. Smudgebiten är till för att dölja namnet i ordlistan. Kodpekaren är ett index till en hopptabell i mikrokodsminnet där den exekverbara mikrokoden finns FORTH-kod består alltså av adresser till kodpekare(!). Denna kod tolkas av en stump mikrokod som liknar det här: @IP -> WA ;IP 24 bitars adress IP+24 -> IP ; 3 byte framåt JMP Tabell+@WA ; WA 24 bitar, ; 8 bitars index i Tabell Tabellen ligger i mikrominnet och innehåller hoppinstruktioner. För ord skrivna i FORTH, högnivåord, är relevanta data en serie adresser (se ovan) till andra ord. Kodpekaren refererar då till mikrokod som sparar IP på returstacken och lägger in WA+8 (dvs första adressen efter kodpekaren) i IP. Serien med adresser avslutas med ett ord som återställer TP från returstacken. Multipla processer i multi-FORTH När en användare sätter sig ner för att köra multi-FORTH kommer han (vi har inga flickor i Lysator) att mötas av en loginprompt. Så fort han har loggat in får han tillgång till ett FORTH-system med 24 och 64 bitars ordlängd, fullständigt flyttalspaket med 64 och 128 bitars flyttal, trädorienterat filsystem, fullständig skärmeditor, virtuellt minne och kraftfulla primitiver för hantering av parallella processer. Minnet på 512 KByte delas upp i två delar; En del som är gemensam för alla processer och där grundFORTHen lagras, och en del som används av de processer som finns. Den första delen innehåller ordlistan, blockbuffertar och gemensamma variabler och semaforer. Den andra delen är i sin tur uppdelad så att varje process har plats för systemvariabler, ordlistor och stackar. Naturligtvis finns inget som hindrar processerna att skriva och läsa varandras minnesareor. Det är nämligen så som processerna kommunicerar med varandra. Den här uppdelningen är endast logisk och inte fysisk, alla processer exekverar i en gemensam adressrymd. En viktig del av ett flerprocessystem är hur man tilldelar processorkraft till processerna. I FORTH är det vanligaste systemet att en process får använda CPUn så länge den vill. Med ett särskilt ord låter man andra processer få tillgång till processorn. Så fungerar också multi-FORTH. En process får dock inte lägga beslag på all processorkraft hur länge som helst. Har den inte lämnat över kontrollen till en annan process inom 1 sekund så återställs processen och placeras sist i processkön. Processkön, en cirkulär länkad lista, finns i mikrominnet. Här finns förutom pekaren till nästa process i kön en pekare till varje process startadress i huvudminnet. I de första orden i processens arbetsarea ligger en del information om processen. Här finns t ex start- och slutadress för processens minne, utrymme för att lagra stackpekare för data- och returstack när processen är inaktiv och startadresser för stackarna och instruktionspekaren. Dessutom finns en flagga som talar om huruvida processen är aktiv eller inte. Det är viktigt att märka att detta inte ligger i mikrominnet eftersom det ger andra processer möjlighet att manipulera alla processparametrar.